package idv.arthur.work.deployment;

import idv.arthur.work.Widgets;
import idv.arthur.work.strucs.WebDep;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.net.telnet.TelnetClient;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import com.google.gson.Gson;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class BeforeDep extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	static Widgets wid = new Widgets();
	static TelnetClient telnet = null;
	static InputStream input = null;
	static PrintStream out = null;
	
    public BeforeDep() {
        super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	doPost(request,response);
    }

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		
		request.setCharacterEncoding( wid.UIcodeSet );
		response.setContentType("application/json");
		response.setCharacterEncoding( wid.UIcodeSet );
		
		final String bssId = "MBMS";
		final String subSysId = request.getParameter("subSysId");
		final String envId = request.getParameter("envId");
		final String split = "##";
		final String currentUser = request.getParameter("loginUser");
		final boolean isByDel = Boolean.parseBoolean( request.getParameter("isByDel") );
		final boolean isReDep = Boolean.parseBoolean( request.getParameter("isReDep") );
		final boolean isContainedWeb = "2".equalsIgnoreCase( request.getParameter("filePortfolio") )?false:true;		//此次部署是否包含 web類型的檔案
		
		Connection conn = null;
		Connection tarConn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		ResultSet rs2 = null;
		String errPars = "}";
		String tmpStr = null;
		
		String unChkList[] = null;	//在批次中，未勾選必需排除的
		
		/** 
		 * --手動部署時使用--
		 * 儲存這次部署，所有要部署的子系統和資源群組
		 * 格式為  subsysid:squadid
		 * */
		ArrayList<String> pile = new ArrayList<String>();						
		ArrayList<WebDep> webDeps = new ArrayList<WebDep>(); 	//	用來儲存web 程式的資訊

		JSch jsch = new JSch();
        JSch.setConfig("StrictHostKeyChecking", "no");
        Session session = null;
        ChannelSftp sftp = null;
        
		Timestamp bTime;
		
		String res = "";
		String strSVNpar = "";
		String modulePath = "";	//模組在AP Server上放的位置
		String wcIP = "";
		String wcLoginId = "";
		String wcPWD = "";
		
		int deliverySN =0;
		int deliveryTarSN = 0;
		int deplmainSN = 0;
		int depmainSN = 0;
		StringBuilder strSQL = new StringBuilder();
		ISVNAuthenticationManager authManager = null;
		SVNRepository repository = null;
		SVNProperties fileProperties = new SVNProperties();
		ByteArrayOutputStream baos = null;
		int tarSysNo = 0;
		
		try {
			conn = wid.getConn(true);
			final int localSysNo = wid.getLocalSysNo( conn, ps, rs);									//取得目前這個系統的身份
			
			if ( !isByDel && isReDep) {	//整批的重新部署
				deplmainSN = Integer.parseInt(request.getParameter("deplmainSN"));
			}
			
			if ( isByDel || isReDep ) {		//交付式部署	或 整批的重新部署
				if ( isByDel ) {
					if ( !"".equalsIgnoreCase( request.getParameter("unChkList") ) ) {
						unChkList = request.getParameter("unChkList").split( wid.splitTokenONE );
						
						/*	
						 * 有unChkList, 表示交付式部署下
						 * 但存在未勾選的項目
						 * 因此必須建立新部署計畫，容納此種組合
						 * 	*/
						deplmainSN = wid.getCurrentSN("deplmain", conn, ps, rs);
						strSQL.replace(0, strSQL.length(), "INSERT INTO deplmain (deplmainSN,sysSN,creator,createdDateTime) VALUES ("+deplmainSN+",?,?,?)" );
						 /* 部署計畫表頭		交付方  */
						ps = conn.prepareStatement( strSQL.toString() );
						ps.setInt(1, localSysNo );
						ps.setString(2, currentUser );
						ps.setTimestamp(3, wid.currentTimeStamp() );
						ps.execute();
						
						strSQL.replace(0, strSQL.length(), "SELECT depldetailid,localFile,localVer,isnonweb,depPath,localPath FROM depldetail WHERE deplmainsn=? AND depldetailid NOT IN ("+request.getParameter("unChkList").replace(wid.splitTokenONE, ",")+")" );
						ps = conn.prepareStatement( strSQL.toString() );
						ps.setInt(1, Integer.parseInt( request.getParameter("deplmainSN") ) );
						rs = ps.executeQuery();
						while ( rs.next() ) {
							//	創建部署計畫的細項
							strSQL.replace(0, strSQL.length(), "INSERT INTO depldetail (deplmainSN,depldetailid,localFile,localVer,isnonweb,depPath,localPath,creator,createdDateTime) VALUES (?,?,?,?,?,?,?,?,?)");
							ps = conn.prepareStatement( strSQL.toString() );
							ps.setInt(1, deplmainSN);	
							ps.setInt(2, rs.getInt("depldetailid") );	//細項的流水號	
							ps.setString(3, rs.getString("localFile") );
							ps.setLong(4, rs.getLong("localVer") );
							ps.setString(5, rs.getString("isnonweb")  );
							ps.setString(6, rs.getString("depPath") );
							ps.setString(7,rs.getString("localPath") );		//SVN路徑
							ps.setString(8, currentUser);
							ps.setTimestamp(9,wid.currentTimeStamp());
							ps.execute();

							/*	新增	 細項與需求間的對應  */
							strSQL.replace(0, strSQL.length(), "SELECT reqsn FROM mpreqfiles WHERE deplmainsn=? AND depldetailid=?" );
							ps = conn.prepareStatement( strSQL.toString() );
							ps.setInt(1, Integer.parseInt( request.getParameter("deplmainSN") ) );
							ps.setInt(2, rs.getInt("depldetailid") );
							rs2 = ps.executeQuery();
							while ( rs2.next() ) {
								strSQL.replace(0, strSQL.length(), "INSERT INTO mpreqfiles (deplmainSN,depldetailid,reqSN,creator,createdDateTime) VALUES (?,?,?,?,?)" );
								ps = conn.prepareStatement( strSQL.toString() );
								ps.setInt(1, deplmainSN);
								ps.setInt(2, rs.getInt("depldetailid") );
								ps.setInt(3, rs2.getInt("reqsn"));
								ps.setString(4, currentUser);
								ps.setTimestamp(5, wid.currentTimeStamp() );
								ps.execute();	
							}
							
							/*	新增	 細項與部署資源間的對應  */
							strSQL.replace(0, strSQL.length(), "SELECT bssid,subsysid,squadid FROM mpdeplunitsqu WHERE deplmainsn=? AND depldetailid=?" );
							ps = conn.prepareStatement( strSQL.toString() );
							ps.setInt(1, Integer.parseInt( request.getParameter("deplmainSN") ) );
							ps.setInt(2, rs.getInt("depldetailid") );
							rs2 = ps.executeQuery();
							while ( rs2.next() ) {
								strSQL.replace(0, strSQL.length(), "INSERT INTO mpdeplunitsqu (deplmainSN,depldetailid,bssid,subsysid,squadid,creator,createdDateTime) VALUES (?,?,?,?,?,?,?)" );
								ps = conn.prepareStatement( strSQL.toString() );
								ps.setInt(1, deplmainSN);
								ps.setInt(2, rs.getInt("depldetailid") );
								ps.setString(3, rs2.getString("bssid"));
								ps.setString(4, rs2.getString("subsysid"));
								ps.setString(5, rs2.getString("squadid"));
								ps.setString(6, currentUser);
								ps.setTimestamp(7, wid.currentTimeStamp() );
								ps.execute();	
							}
						}
					}
					
					strSQL.replace(0, strSQL.length(), "SELECT DISTINCT(t2.subsysid), t2.squadid,t2.deplmainSN,t3.sysSN,t1.deliveryTarSN FROM deltask t1, mpdeplunitsqu t2, deplmain t3 WHERE t1.deplmainSN=t2.deplmainSN AND t3.deplmainSN=t1.deplmainSN AND t1.deliverySN=?");
					
					if ( unChkList != null ) {
						for ( int i=0; i < unChkList.length; i++) {
							strSQL.append(" AND t2.depldetailid<>"+unChkList[i]);
						}
					}
					deliverySN = Integer.parseInt(request.getParameter("deliverSN_q"));
					ps = conn.prepareStatement( strSQL.toString() );
					ps.setInt(1, deliverySN );
				}
				if ( isReDep ) {
					if ( conn.getMetaData().getDatabaseProductName().contains( "MySQL" ) ) {
						strSQL.replace(0, strSQL.length(), "SELECT DISTINCT(t2.subsysid), t2.squadid,t2.deplmainSN,t3.sysSN,t1.deliveryTarSN FROM deltask t1, mpdeplunitsqu t2, deplmain t3 WHERE t1.deplmainSN=t2.deplmainSN AND t3.deplmainSN=t1.deplmainSN AND t3.deplmainSN=?");	
					} else if ( conn.getMetaData().getDatabaseProductName().contains( "Informix" ) ) {
						strSQL.replace(0, strSQL.length(), "SELECT DISTINCT(t2.subsysid), t2.squadid,t2.deplmainSN,t3.sysSN,t1.deliveryTarSN FROM mpdeplunitsqu t2, deplmain t3, OUTER deltask t1 WHERE t1.deplmainSN=t2.deplmainSN AND t2.deplmainSN=t3.deplmainSN AND t3.deplmainSN=t1.deplmainSN AND t3.deplmainSN=?");	
					}
					deplmainSN = Integer.parseInt( request.getParameter("deplmainSN") );
					ps = conn.prepareStatement( strSQL.toString() );
					ps.setInt(1, deplmainSN);
				}
				rs = ps.executeQuery();
				while (rs.next()) {
					tarSysNo = rs.getInt("sysSN");
					
					if ( unChkList == null ) { //沒有存在未勾選的項目時，表示是依照原定計畫計行部署
						deplmainSN = rs.getInt("deplmainSN");	
					}
					
					deliveryTarSN = rs.getInt("deliveryTarSN");
					pile.add(rs.getString(1)+":"+rs.getString(2));
				}
			}
			
			if( localSysNo != tarSysNo ) {
				tarConn = wid.getTarConnection(localSysNo, tarSysNo, conn, ps, rs);
			}
			

			/*	檢查環境的部署順序	*/
			int preClass = 0;
			
			String preDep = "";
			for( int i =0; i<pile.size(); i++ ) {
				if ( i==0 && isContainedWeb ) {
					strSQL.replace(0, strSQL.length(), "SELECT t2.webconsoleip,t2.loginid,t2.pwd,t2.modulepath,t1.envid,t1.envname,t1.preClass FROM env t1,wcl t2 WHERE t1.webconsolesn=t2.webconsolesn AND t1.envid=? AND t1.subsysid=? AND t1.bssid = ?");	
				} else {
					strSQL.replace(0, strSQL.length(), "SELECT envid,envname,preClass FROM env WHERE envid = ? AND subsysid = ? AND bssid = ?");
				}
				
				ps = conn.prepareStatement( strSQL.toString() );
				ps.setString(1, envId );
				ps.setString(2, pile.get(i).split(":")[0] );
				ps.setString(3, bssId );
				rs = ps.executeQuery();
				rs.next();
				
				if ( i==0 && isContainedWeb ) {
					wcIP = rs.getString("webconsoleip");
					modulePath = rs.getString("modulepath");
					wcLoginId = rs.getString("loginid");
					wcPWD = rs.getString("pwd");
				}
				
				preClass = rs.getString("preClass")==null?0:rs.getInt("preClass");
				if ( preClass != 0 ) {	//表示有部署順序限制
					/*
					 *		1. 將有順序的那些環境都找出來
					 *		2.	這些環境都要去查 【各項目主機部署記錄】，看該【部署記畫】，是否有部署過那些 環境 的記錄
					 * */
					
					strSQL.replace(0, strSQL.length(), "SELECT envid,envname FROM env WHERE selfClass=? AND bssid=? AND subsysid=?");
					ps = conn.prepareStatement( strSQL.toString() );
					ps.setInt(1, preClass);
					ps.setString(2, bssId);
					ps.setString(3, pile.get(i).split(":")[0]);
					rs = ps.executeQuery();
					
					/*	這些查到的環境都必須要有部署記錄	*/
					strSQL.replace(0, strSQL.length(), "SELECT COUNT(*) FROM depmain WHERE deplmainSN=? AND envid=?");
					ps = conn.prepareStatement( strSQL.toString() );
					while ( rs.next() ) {
						ps.clearParameters();
						ps.setInt(1, deplmainSN);
						ps.setString(2, rs.getString("envid"));
						rs2 = ps.executeQuery();
						rs2.next();
						if ( rs2.getInt(1)==0 ) {
							if (  preDep.indexOf( wid.DB2UI( rs.getString("envname"),conn.getMetaData().getDatabaseProductName() )+"( "+rs.getString("envid")+ " )") ==-1) {
								preDep += ( wid.DB2UI( rs.getString("envname"),conn.getMetaData().getDatabaseProductName() )+"( "+rs.getString("envid")+ " )\n");	
							}
						}
					}
				}
			}
			
			strSVNpar = wid.getTarSVNConnection(localSysNo, localSysNo, conn, ps, rs,split );
	        repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded( strSVNpar.split(split)[2] + "/" + subSysId ) );
	        authManager = SVNWCUtil.createDefaultAuthenticationManager(strSVNpar.split(split)[0], strSVNpar.split(split)[1]);
	        repository.setAuthenticationManager(authManager);
	        
			if ("".equalsIgnoreCase(preDep) || isReDep ) {
				
				String preFileName = "";		//為了產生用來儲存web 程式資訊 的結構，記錄前一個的檔名
				
				/*	部署記錄單頭	*/
				depmainSN = wid.getCurrentSN("depmain", conn, ps, rs);
				strSQL.replace(0, strSQL.length(), "INSERT INTO depmain (depmainSN,deplmainSN,envid,creator,createdDateTime) VALUES ("+depmainSN+",?,?,?,?)");
				ps = conn.prepareStatement( strSQL.toString() );
				ps.setInt(1, deplmainSN);
				ps.setString(2, envId);
				ps.setString(3, currentUser);
				ps.setTimestamp(4, wid.currentTimeStamp() );	
				ps.execute();
				
				strSQL.replace(0, strSQL.length(), "SELECT t1.isnonweb,t1.depldetailid,t1.deplmainSN,t1.localPath,t1.localFile,t1.localVer,t1.depPath,t2.bssid,t2.subsysid,t2.squadid,t3.squadpath FROM depldetail t1,mpdeplunitsqu t2,squad t3 WHERE t1.deplmainSN=t2.deplmainSN AND t1.depldetailid=t2.depldetailid AND t2.bssid=t3.bssid AND t2.subsysid=t3.subsysid AND t2.squadid=t3.squadid AND t1.deplmainSN=? ORDER BY t1.depldetailid ASC");
				ps = conn.prepareStatement( strSQL.toString() );
				ps.setInt(1, Integer.parseInt( request.getParameter("deplmainSN") ) );	//若是 存在未勾選項目，則 deplmainSN的值，目前會被取代為新建的值，故此時要重新自request取值
				rs = ps.executeQuery();
				
				/*	依一筆筆的部署計畫細項開始執行	*/
				while ( rs.next() ) {
					boolean isChecked=true;
					if ( unChkList != null ) {
						for ( int i=0; i < unChkList.length; i++) {
							if ( Integer.parseInt( unChkList[i] ) == rs.getInt("depldetailid") ) {
								isChecked=false;
							}
						}
					}
					
					if ( isChecked ) {
						final boolean isNonWeb = "t".equalsIgnoreCase( rs.getString("isnonweb") );	//確認此筆部署是否為web部署
						
						
						/**	
						 * 		由於在上一筆的SQL中，是查出所有要去部署計畫細項，要去的squad
						 * 		而一筆部署計畫細項若被要求部署在多個 Squad上，則會有多筆 resultSet
						 * 		但部署記錄與部署計畫又是一對一的對應，因此要執行下面這個COUNT來確認有無新增過部署記錄
						 * 	*/
						strSQL.replace(0, strSQL.length(), "SELECT COUNT(*) FROM depdetail WHERE depmainSN=? AND depdetailid=?");
						ps = conn.prepareStatement( strSQL.toString() );
						ps.setInt(1, depmainSN);
						ps.setInt(2, rs.getInt("depldetailid"));
						rs2 = ps.executeQuery();
						rs2.next();
						
						/**	新增部署記錄細項	*/
						if (rs2.getInt(1)==0) {
							strSQL.replace(0, strSQL.length(), "INSERT INTO depdetail (depmainSN,depdetailid,deplmainSN,depldetailid) VALUES (?,?,?,?)");
							ps = conn.prepareStatement( strSQL.toString() );
							ps.setInt(1, depmainSN);
							ps.setInt(2, rs.getInt("depldetailid"));
							ps.setInt(3, deplmainSN);
							ps.setInt(4, rs.getInt("depldetailid"));
							ps.execute();	
						}
						
						if ( isNonWeb ) {
							strSQL.replace( 0, strSQL.length(), "SELECT t1.ip,t1.port,t2.loginId,t2.loginPWD,t2.hostname FROM mpsquadhosts t1, hosts t2 WHERE t1.bssid=t2.bssid AND t1.subsysid=t2.subsysid AND t1.port=t2.port AND t1.bssid=? AND t1.subsysid=? AND t1.envid=? AND t1.squadid=?");
							ps = conn.prepareStatement( strSQL.toString() );
							ps.setString(1, bssId );
							ps.setString(2, rs.getString("subsysid") );
							ps.setString(3, envId);
							ps.setString(4, rs.getString("squadid") );
							rs2 = ps.executeQuery();
							
							while (rs2.next()) {
								bTime = wid.currentTimeStamp();	//實體部署的啟始時間
								/*
								 * 實體部署
								 * */
								baos = new ByteArrayOutputStream();
								
								if ( "".equalsIgnoreCase( rs.getString("localPath") )) {
									tmpStr = repository.getRepositoryPath("")+"/"+rs.getString("localFile");
								} else {
									tmpStr= repository.getRepositoryPath("")+"/"+rs.getString("localPath") +"/"+rs.getString("localFile");
								}
								
								
								repository.getFile( tmpStr, rs.getLong("localVer"), fileProperties, baos);
								
								session = jsch.getSession(rs2.getString("loginId"), rs2.getString("ip"));
								session.setPassword( rs2.getString("loginPWD") );
						        session.connect();
						        sftp = (ChannelSftp) session.openChannel("sftp");
						        
						        sftp.connect();
								if ( sftp.isConnected() ) {
									
									/*	改變資源群組的路徑	*/
									if (!"".equalsIgnoreCase(rs.getString("squadpath"))) {
										wid.cwd(sftp,rs.getString("squadpath"));
									} 
									
									/*	改變檔案部署的路徑	*/
									if (!"".equalsIgnoreCase( rs.getString("depPath") )) {
										String tmp = rs.getString("depPath");
										if ( tmp.startsWith("/") ) {
											tmp= tmp.substring(1, tmp.length());
										}
										wid.cwd(sftp, tmp);
									}
									
									// 如果傳的是// war要加這行
									input = new ByteArrayInputStream(baos.toByteArray());
									sftp.put(input, rs.getString("localFile"), ChannelSftp.OVERWRITE);

									
									
									/** 改變檔案的權限，因為要執行 */
									sftp.chmod( wid.ACCESSRIGHT, rs.getString("localFile") );
									
									/*	寫入Log	*/
									strSQL.replace(0, strSQL.length(), "INSERT INTO itemdeplog (depmainSN,depdetailid,bssid,subsysid,envid,squadid,ip,port,squadpath,depRes,depsLog,bTime,eTime) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
									ps = conn.prepareStatement( strSQL.toString() );
									
									ps.setInt(1, depmainSN);
									ps.setInt(2, rs.getInt("depldetailid") );
									ps.setString(3, bssId);
									ps.setString(4, rs.getString("subsysid") );
									ps.setString(5, envId);
									ps.setString(6, rs.getString("squadid") );
									ps.setString(7, rs2.getString("ip") );
									ps.setInt(8, rs2.getInt("port") );
									ps.setString(9, rs.getString("squadpath") );
									ps.setInt(10, 1);
									ps.setString(11, "");
									ps.setTimestamp(12, bTime);
									ps.setTimestamp(13, wid.currentTimeStamp());
									ps.execute();
									
									res += rs.getString("localFile")+"\t 大小:"+baos.size()+" bytes\t部署於  "+wid.DB2UI( rs2.getString("hostname"),conn.getMetaData().getDatabaseProductName() )+".......完成\n";
								} else {
									res += "無法登入主機+"+rs2.getString("hostname")+"!!";
									System.out.println(res);
								}
							}
						} else {		//web
							if ( preFileName.equalsIgnoreCase( rs.getString("localFile") ) ) {
								webDeps.get( webDeps.size()-1 ).getSquads().add( rs.getString("squadid") );
							} else {
								WebDep webDep = new WebDep();
								webDep.setModuleName( rs.getString("localFile").substring( 0, wid.DB2UI(rs.getString("localFile"),conn.getMetaData().getDatabaseProductName()).lastIndexOf(".") ) );	//只取檔名的部份，故用. 來做lastIndexOf
								webDep.setExt( rs.getString("localFile").substring( wid.DB2UI(rs.getString("localFile"),conn.getMetaData().getDatabaseProductName()).lastIndexOf("."), wid.DB2UI(rs.getString("localFile"),conn.getMetaData().getDatabaseProductName()).length() ) );
								ArrayList<String> squad = new ArrayList<String>();
								squad.add( rs.getString("squadid") );
								webDep.setSquads(squad);
								webDeps.add(webDep);
							}
							
							bTime = wid.currentTimeStamp();	//實體部署的啟始時間
							
							/*
							 * 實體部署
							 * */
							baos = new ByteArrayOutputStream();
							
							if ( "".equalsIgnoreCase( rs.getString("localPath") )) {
								tmpStr = repository.getRepositoryPath("")+"/"+rs.getString("localFile");
							} else {
								tmpStr= repository.getRepositoryPath("")+"/"+rs.getString("localPath") +"/"+rs.getString("localFile");
							}
							repository.getFile( tmpStr, rs.getLong("localVer"), fileProperties, baos);
							
							session = jsch.getSession( wcLoginId, wcIP );
							session.setPassword( wcPWD );
					        session.connect();
					        sftp = (ChannelSftp)  session.openChannel("sftp");
					        sftp.connect();
							if ( sftp.isConnected() ) {
								
								/*	切換到AP Server放模組地方的路徑	*/
								if (!"".equalsIgnoreCase( modulePath )) {
									wid.cwd( sftp, modulePath );
								} 
								
								input = new ByteArrayInputStream(baos.toByteArray());
								sftp.put(input, rs.getString("localFile"), ChannelSftp.OVERWRITE);
								
								/** 改變檔案的權限，因為要執行 */
								sftp.chmod( wid.ACCESSRIGHT, rs.getString("localFile") );
								
								/*	寫入Log	*/
								strSQL.replace(0, strSQL.length(), "INSERT INTO itemdeplog (depmainSN,depdetailid,bssid,subsysid,envid,squadid,ip,port,squadpath,depRes,depsLog,bTime,eTime) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
								ps = conn.prepareStatement( strSQL.toString() );
								
								ps.setInt(1, depmainSN);
								ps.setInt(2, rs.getInt("depldetailid") );
								ps.setString(3, bssId);
								ps.setString(4, rs.getString("subsysid") );
								ps.setString(5, envId);
								ps.setString(6, rs.getString("squadid") );
								ps.setString(7, wcIP );
								ps.setInt(8, 7382 );								// web的程式 port都寫成7382
								ps.setString(9, modulePath );				// 原本的squadPath，皆寫入目前設定的 AP Server放模組地方的路徑
								ps.setInt(10, 1);
								ps.setString(11, "");
								ps.setTimestamp(12, bTime);
								ps.setTimestamp(13, wid.currentTimeStamp());
								ps.execute();
								
								res += "更新檔案完成\n";
							} else {
								res += "無法登入主機!!";
								System.out.println(res);
							}
						}
					}
				}
				
				/*	檔案放到AP Server了，現在要起動它	*/
				if ( isContainedWeb ) {
					telnet = new TelnetClient();
					telnet.connect(wcIP, 23);
					telnet.setSoTimeout( 1200000 );
		            out = new PrintStream( telnet.getOutputStream() );
		            input = telnet.getInputStream();
		            wid.readUntil("login: ",input);
		            wid.write( wcLoginId,out );
		            wid.readUntil("Password: ",input);
		            wid.write( wcPWD,out  );
		            wid.sendCommand("cd " + modulePath,input,out);  //切換到部署目錄
					
					for( int i=0; i< webDeps.size(); i++ ) {

						/**
						 * 	i代表的是web程式
						 * j代表的是程式所要去的 squad
						 */
						String squads = "";
						for (int j=0; j < webDeps.get(i).getSquads().size(); j++ ) {
							squads += webDeps.get(i).getSquads().get(j)+",";
						}
						squads = squads.substring( 0, squads.length()-1 ); //-1是為了扣掉那個 ,
						
						String deployCommand = wid.composeCommand(wcIP, wcLoginId, wcPWD, webDeps.get(i).getModuleName(),webDeps.get(i).getModuleName()+"."+webDeps.get(i).getExt(), squads, "redeploy");  //組合部署指令
		            	
		                wid.sendCommand( deployCommand,input,out );  //執行部署指令
		                String ret = wid.readUntil(modulePath + "> ",input);
		                res = wid.splitTokenONE+wid.deployInfo(ret);
		                
		                for ( int m=0; m<webDeps.size();m++) {
		                	res += "\n"+webDeps.get(m).getModuleName();
		                }
		                
		                if ( !"Redeploy successfully.".equalsIgnoreCase( wid.deployInfo(ret) ) ) {
		                	errPars = wid.toJend("result", res);
		        			wid.kem(conn, ps, new Exception(), wid.toEType("Bug Trace")+errPars, false);
		                } else {
		                	res = "部署完成";
		                }
					}
				}
				
				/**	
				 * 		若是以部署計畫代碼來部署，
				 * 		需要更新流程的狀態 
				 * */
				if ( isByDel ) {
					strSQL.replace(0, strSQL.length(), "UPDATE deltask SET statusSN=4 WHERE deliverySN=?");
					ps = conn.prepareStatement( strSQL.toString() );
					ps.setInt(1, deliverySN);
					ps.execute();
					
					if( localSysNo != tarSysNo ) {
						strSQL.replace(0, strSQL.length(), "UPDATE deltask SET statusSN=4 WHERE deliverySN=?");
						ps = tarConn.prepareStatement( strSQL.toString() );
						ps.setInt(1, deliveryTarSN);
						ps.execute();
					}	
				}
			} else {
				res = "需要先部署下列環境：\n" + preDep + "\n";
			}
		
		} catch ( UnsupportedEncodingException e ) {
			res = wid.kem(conn, ps, e, wid.toEType("UnsupportedEncodingException")+errPars, wid.isPrint2Console );
		} catch ( SQLException e) {
			res = wid.kem(conn, ps, e, wid.toEType("SQLException")+errPars, wid.isPrint2Console );
		} catch ( JSchException e) {
			res = wid.kem(conn, ps, e, wid.toEType("JSchException")+errPars, wid.isPrint2Console );
			if (res.contains("Auth fail")) {
				res = "帳密有誤!\n無法登入\n"+strSVNpar.split(split)[2];		
			}
		} catch ( Exception e) {
			if ( res.contains( wid.splitTokenONE ) ) {
				res = res.substring(wid.splitTokenONE.length(),res.length());
			} else {
				res = wid.kem(conn, ps, e, wid.toEType("Exception")+errPars, wid.isPrint2Console );
			}
		} finally {
			try {
				if ( input != null ) { input.close(); }
				if ( out != null ) {
					wid.write("exit",out );
					out.close();
				}
				if ( baos != null ) { baos.close(); }
				if ( rs != null ) {rs.close();}
				if ( rs2 != null ) {rs2.close();}
				if ( ps != null ) {ps.close();}
				if ( conn != null ) {conn.close();}
				if ( tarConn != null ) {tarConn.close();}
				if ( telnet != null ) { if ( telnet.isConnected() ) { telnet.disconnect(); } }
				if ( sftp != null ) { if ( sftp.isConnected() ) { sftp.disconnect(); } }
				if ( session != null ) { if ( session.isConnected() ) { session.disconnect(); } }
			} catch (SQLException e) {
				System.out.println( wid.errProcess(e) );
			}
		}
		
		response.getWriter().write(new Gson().toJson(res));
	}
}